package cn.limbo.myandserver.controller;


import android.content.Context;
import android.support.annotation.Nullable;
import cn.limbo.myandserver.PathManager;
import cn.limbo.myandserver.dao.DatabaseUtils;
import cn.limbo.myandserver.model.FileModel;
import cn.limbo.myandserver.utils.FileUtils;
import cn.limbo.myandserver.utils.JsonUtils;
import cn.limbo.myandserver.utils.MD5;
import com.yanzhenjie.andserver.annotation.*;
import com.yanzhenjie.andserver.framework.body.FileBody;
import com.yanzhenjie.andserver.http.HttpResponse;
import com.yanzhenjie.andserver.http.ResponseBody;
import com.yanzhenjie.andserver.http.multipart.MultipartFile;
import com.yanzhenjie.andserver.util.MediaType;
import com.yanzhenjie.andserver.util.ObjectUtils;
import org.apache.commons.io.Charsets;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;

/**
 * 文件功能控制模块
 */

@RestController
@RequestMapping("/file")
public class FileController {

    /**
     * 数据库工具对象
     */
    private DatabaseUtils utils;

    /**
     * 从数据库中检查所要上传的文件的文件名和MD5值是否存在
     * @param fileName 文件名
     * @param MD5 文件的MD5值
     * @param context 上下文对象
     * @return 检查结果
     */
    @Addition(stringType = "needLogin", booleanType = true)
    @GetMapping("/checkMD5")
    String checkMD5(@RequestParam(name = "fileName") String fileName, @RequestParam(name = "MD5") String MD5, Context context) {
        utils = new DatabaseUtils(context);
        ArrayList<FileModel> models = utils.queryFromFile();
        for (FileModel model : models) {
            if (fileName.equals(model.getFileName())) {
                if (MD5.equals(model.getFileMD5())) {
                    return JsonUtils.getJson(1, "服务器中存在同名文件，且无差异，请勿重复上传！");
                } else {
                    return JsonUtils.getJson(2, "服务器中存在同名文件，但略有不同，上传后将会改名为‘文件名’+‘_副本’的形式！");
                }
            }
        }
        return JsonUtils.getJson(0, "服务器中无同名文件，可放心上传！");
    }

    /**
     * 检查文件是否成功上传
     * @param file 上传的文件
     * @param context 上下文对象
     * @return 文件上传的结果
     * @throws IOException 异常
     */
    @Addition(stringType = "needLogin", booleanType = true)
    @PostMapping("/uploadFile")
    String upload(@RequestParam(name = "file") MultipartFile file, Context context) throws IOException {
        utils = new DatabaseUtils(context);
        ArrayList<FileModel> models = utils.queryFromFile();
        for (FileModel model : models) {
            if (model.getFileName().equals(file.getFilename())) {
                if (model.getFileMD5().equals(MD5.md5(file))) {
                    return JsonUtils.getJson(1, "上传失败，文件已存在！");
                } else {
                    File localFile = new File(PathManager.getInstance().getWebDir() + "/Files/" + file.getFilename() + "_副本");
                    file.transferTo(localFile);
                    utils.addToFile(localFile.getName(), MD5.md5(localFile));
                    return JsonUtils.getJson(0, "上传成功！文件地址为：【" + localFile.getAbsolutePath() + "】");
                }
            }
        }
        File localFile = new File(PathManager.getInstance().getWebDir() + "/Files/" + file.getFilename());
        file.transferTo(localFile);
        utils.addToFile(localFile.getName(), MD5.md5(localFile));
        return JsonUtils.getJson(0, "上传成功！文件地址为：【" + localFile.getAbsolutePath() + "】");
    }

    /**
     * 文件列表浏览器功能
     * @return 文件列表对象
     * @throws IOException 异常
     */
    @Addition(stringType = "needLogin", booleanType = true)
    @GetMapping("/list")
    ResponseBody fileList() throws IOException {
        File resource = new File(PathManager.getInstance().getWebDir() + "/Files");
        File tempFile = File.createTempFile("file_browser", ".html");
        OutputStream os = new FileOutputStream(tempFile);
        String prefix = String.format(FileUtils.FOLDER_HTML_PREFIX, "文件浏览器", "文件下载");
        os.write(prefix.getBytes(StandardCharsets.UTF_8));

        File[] files = resource.listFiles();
        if (!ObjectUtils.isEmpty(files)) {
            for (File file : files) {
                String fileSize = FileUtils.getSize(file);
                String fileItem = String.format(FileUtils.FOLDER_ITEM, file.getName(), fileSize);
                os.write(fileItem.getBytes(StandardCharsets.UTF_8));
            }
        }

        os.write(FileUtils.FOLDER_HTML_SUFFIX.getBytes(StandardCharsets.UTF_8));
        return new FileBody(tempFile) {
            @Nullable
            @Override
            public MediaType contentType() {
                MediaType mimeType = super.contentType();
                if (mimeType != null) {
                    mimeType = new MediaType(mimeType.getType(), mimeType.getSubtype(), Charsets.UTF_8);
                }
                return mimeType;
            }
        };
    }

    /**
     * 下载文件
     * @param filename 需要下载文件的文件名
     * @param response response对象
     */
    @Addition(stringType = "needLogin", booleanType = true)
    @GetMapping("/ota/{filename}")
    void download(@PathVariable(name = "filename") String filename, HttpResponse response) {
        File file = new File(PathManager.getInstance().getWebDir() + "/Files/" + filename);
        FileBody fileBody = null;
        if (file.exists()) {
            fileBody = new FileBody(file);
        }
        ResponseBody responseBody = fileBody;
        response.setHeader("Content-Disposition", "attachment");
        response.setBody(responseBody);
    }

    /**
     * 在线预览功能（视频、图片、音频文件）
     * @return 在线预览界面
     * @throws IOException 异常
     */
    @Addition(stringType = "needLogin", booleanType = true)
    @GetMapping("/display")
    ResponseBody fileDisplay() throws IOException {
        File resource = new File(PathManager.getInstance().getWebDir() + "/Files");
        File tempFile = File.createTempFile("file_browser", ".html");
        OutputStream os = new FileOutputStream(tempFile);
        String prefix = String.format(FileUtils.FOLDER_HTML_PREFIX, "文件浏览器", "在线预览");
        os.write(prefix.getBytes(StandardCharsets.UTF_8));

        File[] files = resource.listFiles();
        if (!ObjectUtils.isEmpty(files)) {
            for (File file : files) {
                String name = file.getName();
                for (String str : videoEnds) {
                    if (name.toLowerCase().endsWith(str.toLowerCase())) {
                        String fileSize = FileUtils.getSize(file);
                        String fileItem = String.format(FileUtils.FOLDER_VIDEO_ITEM, file.getName(), "视频", fileSize);
                        os.write(fileItem.getBytes(StandardCharsets.UTF_8));
                    }
                }
                for (String str : pictureEnds) {
                    if (name.toLowerCase().endsWith(str.toLowerCase())) {
                        String fileSize = FileUtils.getSize(file);
                        String fileItem = String.format(FileUtils.FOLDER_IMAGE_ITEM, file.getName(), "图片", fileSize);
                        os.write(fileItem.getBytes(StandardCharsets.UTF_8));
                    }
                }
                for (String str : audioEnds) {
                    if (name.toLowerCase().endsWith(str.toLowerCase())) {
                        String fileSize = FileUtils.getSize(file);
                        String fileItem = String.format(FileUtils.FOLDER_AUDIO_ITEM, file.getName(), "音频", fileSize);
                        os.write(fileItem.getBytes(StandardCharsets.UTF_8));
                    }
                }
            }
        }
        os.write(FileUtils.FOLDER_HTML_SUFFIX.getBytes(StandardCharsets.UTF_8));
        return new FileBody(tempFile) {
            @Nullable
            @Override
            public MediaType contentType() {
                MediaType mimeType = super.contentType();
                if (mimeType != null) {
                    mimeType = new MediaType(mimeType.getType(), mimeType.getSubtype(), Charsets.UTF_8);
                }
                return mimeType;
            }
        };
    }

    /**
     * 视频在线播放功能（基于HTML5）
     * @param filename 视频文件名
     * @param response response对象
     * @throws IOException 异常
     */
    @Addition(stringType = "needLogin", booleanType = true)
    @GetMapping("/video/{filename}")
    void video(@PathVariable(name = "filename") String filename, HttpResponse response) throws IOException {
        File tempFile = File.createTempFile("video", ".html");
        OutputStream os = new FileOutputStream(tempFile);
        String html = String.format(FileUtils.VIDEO_PLAY, filename, "100%", "../../Files/" + filename);
        os.write(html.getBytes(StandardCharsets.UTF_8));
        response.setBody(new FileBody(tempFile) {
            @Nullable
            @Override
            public MediaType contentType() {
                MediaType mimeType = super.contentType();
                if (mimeType != null) {
                    mimeType = new MediaType(mimeType.getType(), mimeType.getSubtype(), Charsets.UTF_8);
                }
                return mimeType;
            }
        });
    }

    /**
     * 图片在线预览功能
     * @param filename 图片文件名
     * @param response response对象
     * @throws IOException 异常
     */
    @Addition(stringType = "needLogin", booleanType = true)
    @GetMapping("/image/{filename}")
    void image(@PathVariable(name = "filename") String filename, HttpResponse response) throws IOException {
        File tempFile = File.createTempFile("image", ".html");
        OutputStream os = new FileOutputStream(tempFile);
        String html = String.format(FileUtils.IMAGE_PLAY, filename, "../../Files/" + filename, "100%");
        os.write(html.getBytes(StandardCharsets.UTF_8));
        response.setBody(new FileBody(tempFile) {
            @Nullable
            @Override
            public MediaType contentType() {
                MediaType mimeType = super.contentType();
                if (mimeType != null) {
                    mimeType = new MediaType(mimeType.getType(), mimeType.getSubtype(), Charsets.UTF_8);
                }
                return mimeType;
            }
        });
    }

    /**
     * 音频在线播放功能
     * @param filename 音频文件名
     * @param response response对象
     * @throws IOException 异常
     */
    @Addition(stringType = "needLogin", booleanType = true)
    @GetMapping("/audio/{filename}")
    void audio(@PathVariable(name = "filename") String filename, HttpResponse response) throws IOException {
        File tempFile = File.createTempFile("image", ".html");
        OutputStream os = new FileOutputStream(tempFile);
        String html = String.format(FileUtils.AUDIO_PLAY, filename, "../../Files/" + filename);
        os.write(html.getBytes(StandardCharsets.UTF_8));
        response.setBody(new FileBody(tempFile) {
            @Nullable
            @Override
            public MediaType contentType() {
                MediaType mimeType = super.contentType();
                if (mimeType != null) {
                    mimeType = new MediaType(mimeType.getType(), mimeType.getSubtype(), Charsets.UTF_8);
                }
                return mimeType;
            }
        });
    }

    /*
        在线预览文件后缀名
     */
    private String[] videoEnds = {".mp4", ".avi", ".mov", ".wmv", ".ogg", ".webm", ".mkv", ".rmvb"};
    private String[] pictureEnds = {".jpg", "jpe", ".png", ".gif", ".jpeg"};
    private String[] audioEnds = {".mp3",".ogg", ".flac"};
}
